package com.ibeeking.found.cop.b.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.config.prop.FileOssProp;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.cop.api.common.dto.OssPolicyDto;
import com.ibeeking.found.cop.api.feign.FileFeignClient;
import com.ibeeking.found.cop.b.rest.service.IGroupQrcodeService;
import com.ibeeking.found.cop.b.rest.service.IMqService;
import com.ibeeking.found.cop.b.rest.service.IWxOpenService;
import com.ibeeking.found.cop.service.common.dos.GroupQrcodeDO;
import com.ibeeking.found.cop.service.common.dos.GroupQrcodeGroupDO;
import com.ibeeking.found.cop.service.common.enums.MqSyncOperatorTypeEnum;
import com.ibeeking.found.cop.service.common.enums.WxCpGroupJoinSceneEnum;
import com.ibeeking.found.cop.service.common.param.GroupQrcodeParam;
import com.ibeeking.found.cop.service.common.param.MqSyncCopParam;
import com.ibeeking.found.cop.service.common.query.GroupQrcodePageQuery;
import com.ibeeking.found.cop.service.common.query.GroupQrcodeQuery;
import com.ibeeking.found.cop.service.common.vo.GroupQrcodeVO;
import com.ibeeking.found.cop.service.mapper.GroupQrcodeGroupMapper;
import com.ibeeking.found.cop.service.mapper.GroupQrcodeMapper;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.file.FileUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import me.chanjar.weixin.cp.api.WxCpExternalContactService;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpBaseResp;
import me.chanjar.weixin.cp.bean.external.WxCpGroupJoinWayInfo;
import me.chanjar.weixin.cp.bean.external.WxCpGroupJoinWayResult;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName FriendsTagsServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-01-27 18:50
 **/
@Service
public class GroupQrcodeServiceImpl  extends ServiceImpl<GroupQrcodeMapper, GroupQrcodeDO> implements IGroupQrcodeService {

    @Resource
    private GroupQrcodeMapper groupQrcodeMapper;

    @Resource
    private GroupQrcodeGroupMapper groupQrcodeGroupMapper;

    @Resource
    private IMqService mqServiceImpl;

    @Resource
    private IWxOpenService wxOpenServiceImpl;

    @Resource
    private FileFeignClient fileFeignClient;

    @Resource
    private FileOssProp fileOssProp;

    @Override
    public List<GroupQrcodeVO> list(GroupQrcodeQuery query) {
        List<GroupQrcodeDO> entityDOS = groupQrcodeMapper.selectList(new LambdaQueryWrapper<GroupQrcodeDO>()
                .eq(query.getId() != null, GroupQrcodeDO::getId, query.getId())
                .eq(query.getGroupId() != null, GroupQrcodeDO::getClassId, query.getGroupId())
                .like(StringUtils.isNotBlank(query.getName()), GroupQrcodeDO::getName, query.getName())
                .eq(query.getStatus() != null, GroupQrcodeDO::getStatus, query.getStatus())
                .orderByDesc(GroupQrcodeDO::getCreateTime)
        );
        List<GroupQrcodeVO> entityVOS =JsonUtils.jsonToList(entityDOS, GroupQrcodeVO.class);
        entityVOS.forEach(x -> {
            x.setStatusDesc(PublishStatusEnum.getName(x.getStatus()));
        });
        return entityVOS;
    }

    @Override
    public Page<GroupQrcodeVO> pageList(GroupQrcodePageQuery pageQuery) {
        LambdaQueryWrapper<GroupQrcodeDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(pageQuery.getId() != null, GroupQrcodeDO::getId, pageQuery.getId())
                .eq(pageQuery.getClassId() != null, GroupQrcodeDO::getClassId, pageQuery.getClassId())
                .like(StringUtils.isNotBlank(pageQuery.getName()), GroupQrcodeDO::getName, pageQuery.getName())
                .eq(pageQuery.getStatus() != null, GroupQrcodeDO::getStatus, pageQuery.getStatus())
                .orderByDesc(GroupQrcodeDO::getCreateTime);
        Page<GroupQrcodeDO> entityDOPages = groupQrcodeMapper.selectPage(new Page<GroupQrcodeDO>(pageQuery.getPageNum(), pageQuery.getPageSize()), wrapper);
        Page<GroupQrcodeVO> entityVOPages = BeanUtil.convertPage(entityDOPages, GroupQrcodeVO.class);
        entityVOPages.getRecords().forEach(f ->{
            f.setStatusDesc(PublishStatusEnum.getName(f.getStatus()));
        });
        return entityVOPages;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(GroupQrcodeParam param) {
        checkUnique(param);
        GroupQrcodeDO entityDO = BeanUtil.convertBean(param, GroupQrcodeDO.class);
        Long id = GenerateId.generateId();
        entityDO.setId(id);
        entityDO.setSceneType(WxCpGroupJoinSceneEnum.GROUP_JOIN_SCENE_QRCODE.getCode());
        entityDO.setCreateBy(UserUtils.getUserId());
        entityDO.setCreateTime(LocalDateTime.now());
        entityDO.setModifyTime(LocalDateTime.now());

        boolean result =  groupQrcodeMapper.insert(entityDO) > 0;
        //getBean().sendInstructionToMq(entityDO.getId(), MqSyncOperatorTypeEnum.COP_SYNC_GROUP_ADD_JOIN_WAY.getCode());
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean modify(GroupQrcodeParam param) {
        GroupQrcodeDO entityDO = BeanUtil.convertBean(param, GroupQrcodeDO.class);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());
        boolean result = groupQrcodeMapper.updateById(entityDO) > 0;
        //getBean().sendInstructionToMq(entityDO.getId(), MqSyncOperatorTypeEnum.COP_SYNC_GROUP_UPDATE_JOIN_WAY.getCode());
        return result;
    }

    @Override
    public GroupQrcodeVO view(Long id) {
        GroupQrcodeDO entityDO = groupQrcodeMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        GroupQrcodeVO entityVO = BeanUtil.convertBean(entityDO, GroupQrcodeVO.class);
        if(entityVO != null) {
            entityVO.setStatusDesc(PublishStatusEnum.getName(entityDO.getStatus()));
        }
        return entityVO;
    }

    @Override
    public Integer summaryCount(Long classId){
        if(classId==1L) classId = null;
        return super.count(new LambdaQueryWrapper<GroupQrcodeDO>().eq(GroupQrcodeDO::getClassId, classId));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status) {
        GroupQrcodeDO entityDO = groupQrcodeMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        entityDO.setStatus(status);
        entityDO.setModifyBy(UserUtils.getUserId());
        entityDO.setModifyTime(LocalDateTime.now());

        return groupQrcodeMapper.updateById(entityDO) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        GroupQrcodeDO entityDO = groupQrcodeMapper.selectById(id);
        if(entityDO == null) throw new BusinessException("没有查到相关记录！");
        //getBean().sendInstructionToMq(id, MqSyncOperatorTypeEnum.COP_SYNC_GROUP_DEL_JOIN_WAY.getCode());
        return groupQrcodeMapper.deleteById(id) > 0;
    }
    /***
     *
     * 向Mq发送执行指令
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean sendInstructionToMq(Long qrcodeId, String operType){
        String tenantId = UserUtils.getTenantId();
        MqSyncCopParam mqParam = new MqSyncCopParam();
        mqParam.setTenantId(Long.valueOf(tenantId));
        mqParam.setId(qrcodeId);
        mqParam.setOperType(operType);
        mqServiceImpl.sendSyncToWxTaskMessage(mqParam);
        return true;
    }
    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(GroupQrcodeParam param) {
        if (param == null) {
            throw new BusinessException("当前记录不存在!");
        }
        //code name确保等级唯一性
        LambdaQueryWrapper<GroupQrcodeDO> queryWrapper = new LambdaQueryWrapper<GroupQrcodeDO>()
                .ne(param.getId() != null, GroupQrcodeDO::getId, param.getId())
                .eq(GroupQrcodeDO::getName, param.getName());
        List<GroupQrcodeDO> dos = groupQrcodeMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在同名的记录!");
        }
    }

    /***
     *
     * 企业微信-配置客户群进群方式
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean wxCpProcessGroupAddJoinWay(Integer tenantId, Long qrcodeId, String operType){
        if(qrcodeId == null) throw new BusinessException("发送任务获取消息参数qrcodeId为空");
        GroupQrcodeDO groupQrcodeDO = groupQrcodeMapper.selectById(qrcodeId);
        if(groupQrcodeDO == null) throw new BusinessException("通过qrcodeId获得的消息数据为空!");

        WxCpService wxCpService = wxOpenServiceImpl.getWxCpService(tenantId.longValue());
        WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
        if (wxCpConfigStorage == null) {
            throw new BusinessException("获取企微服务失败!");
        }
        WxCpExternalContactService wxCpExternalContactService = wxCpService.getExternalContactService();
        if (wxCpExternalContactService == null) throw new BusinessException("获取企微服务外部联系人服务!");
        try {
            if(operType.equalsIgnoreCase(MqSyncOperatorTypeEnum.COP_SYNC_GROUP_ADD_JOIN_WAY.getCode())) {
                List<GroupQrcodeGroupDO> qrcodeGroupDOList = groupQrcodeGroupMapper.selectList(new LambdaQueryWrapper<GroupQrcodeGroupDO>().eq(GroupQrcodeGroupDO::getQrcodeId,qrcodeId));
                List<String> chatIdList = Collections3.isNotEmpty(qrcodeGroupDOList)?qrcodeGroupDOList.stream().map(GroupQrcodeGroupDO::getChatId).collect(Collectors.toList()) : null;

                WxCpGroupJoinWayInfo.JoinWay groupJoinWay = new WxCpGroupJoinWayInfo.JoinWay();
                groupJoinWay.setAutoCreateRoom(groupQrcodeDO.getAutoNewGroup());
                groupJoinWay.setChatIdList(chatIdList);
                groupJoinWay.setRemark(groupQrcodeDO.getSceneDescription());
                groupJoinWay.setRoomBaseName(groupQrcodeDO.getNewGroupBase());
                groupJoinWay.setRoomBaseId(groupQrcodeDO.getNewGroupNo());
                groupJoinWay.setScene(groupQrcodeDO.getSceneType());
                groupJoinWay.setState(groupQrcodeDO.getState());
                WxCpGroupJoinWayInfo groupJoinWayInfo = new WxCpGroupJoinWayInfo();
                groupJoinWayInfo.setJoinWay(groupJoinWay);
                WxCpGroupJoinWayResult wxCpGroupJoinWayResult = wxCpExternalContactService.addJoinWay(groupJoinWayInfo);
                if (wxCpGroupJoinWayResult != null && wxCpGroupJoinWayResult.success()) {
                    String configId = wxCpGroupJoinWayResult.getConfigId();
                    if (StringUtils.isNotEmpty(configId)) {
                        WxCpGroupJoinWayInfo wxCpGroupJoinWayInfo = wxCpExternalContactService.getJoinWay(configId);
                        if (wxCpGroupJoinWayInfo != null) {
                            WxCpGroupJoinWayInfo.JoinWay rtngroupJoinWay = wxCpGroupJoinWayInfo.getJoinWay();
                            if (rtngroupJoinWay != null) {
                                OssPolicyDto ossPolicyDto = getOssFilePolicy();
                                String qrCodeUrl = rtngroupJoinWay.getQrCode();
                                if (StringUtils.isNotEmpty(qrCodeUrl)) {
                                    String qrCodePicOssFilePath = transferFileToOss(qrcodeId + "_qrcode", qrCodeUrl, ossPolicyDto);
                                    groupQrcodeDO.setQrcodeUrl(qrCodePicOssFilePath);
                                    groupQrcodeDO.setQrcodeUrlWxcp(qrCodeUrl);
                                    groupQrcodeDO.setConfigId(configId);
                                    groupQrcodeMapper.updateById(groupQrcodeDO);
                                }
                            }
                        }
                    }
                }
                return true;
            }else if(operType.equalsIgnoreCase(MqSyncOperatorTypeEnum.COP_SYNC_GROUP_UPDATE_JOIN_WAY.getCode())) {
                List<GroupQrcodeGroupDO> qrcodeGroupDOList = groupQrcodeGroupMapper.selectList(new LambdaQueryWrapper<GroupQrcodeGroupDO>().eq(GroupQrcodeGroupDO::getQrcodeId,qrcodeId));
                List<String> chatIdList = Collections3.isNotEmpty(qrcodeGroupDOList)?qrcodeGroupDOList.stream().map(GroupQrcodeGroupDO::getChatId).collect(Collectors.toList()) : null;

                WxCpGroupJoinWayInfo.JoinWay groupJoinWay = new WxCpGroupJoinWayInfo.JoinWay();
                groupJoinWay.setConfigId(groupQrcodeDO.getConfigId());

                groupJoinWay.setAutoCreateRoom(groupQrcodeDO.getAutoNewGroup());
                groupJoinWay.setChatIdList(chatIdList);
                groupJoinWay.setRemark(groupQrcodeDO.getSceneDescription());
                groupJoinWay.setRoomBaseName(groupQrcodeDO.getNewGroupBase());
                groupJoinWay.setRoomBaseId(groupQrcodeDO.getNewGroupNo());
                groupJoinWay.setScene(groupQrcodeDO.getSceneType());
                groupJoinWay.setState(groupQrcodeDO.getState());
                groupJoinWay.setQrCode(groupQrcodeDO.getQrcodeUrlWxcp());

                WxCpGroupJoinWayInfo groupJoinWayInfo = new WxCpGroupJoinWayInfo();
                groupJoinWayInfo.setJoinWay(groupJoinWay);
                WxCpBaseResp wxCpBaseResp = wxCpExternalContactService.updateJoinWay(groupJoinWayInfo);
                if (wxCpBaseResp != null && wxCpBaseResp.success()) {
                    return true;
                }else{
                    return false;
                }
            }else if(operType.equalsIgnoreCase(MqSyncOperatorTypeEnum.COP_SYNC_GROUP_DEL_JOIN_WAY.getCode())) {
                String configId= groupQrcodeDO.getConfigId();
                WxCpBaseResp wxCpBaseResp = wxCpExternalContactService.delJoinWay(configId);
                if (wxCpBaseResp != null && wxCpBaseResp.success()) {
                    return true;
                }else{
                    return false;
                }
            }
        }catch (Exception e) {
            LogUtils.error("处理客户群进群方式服务出现异常，原因：{}",e);
            return false;
        }
        return true;
    }


    private String transferFileToOss(String id, String fileUrl, OssPolicyDto policy){
        try {
            String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(id).concat(".png"));
            String fileTag = policy.getDir() + fileName;
            MultipartFile multipartFile = FileUtils.getMultipartFile(fileUrl, fileName, fileTag);
            ResponseResult<String> responseResult = fileFeignClient.uploadFile(multipartFile);
            String fileUploadPath = responseResult.getData();
            return UrlUtils.removeUrlDomainName(fileUploadPath);
        } catch (Exception ex) {
            throw new BusinessException("上传头像文件失败：" + ex.toString());
        }
    }

    private OssPolicyDto getOssFilePolicy(){
        ResponseResult<OssPolicyDto> responseResult = fileFeignClient.policy();
        return responseResult.getData();
    }

    private  IGroupQrcodeService getBean(){
        return SpringBeanUtil.getBean(GroupQrcodeServiceImpl.class);
    }

}
